home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games Extra 1996 September / Amiga Games Extra CD-ROM 9-1996.iso / spiele / publicdomain / elan / src / os2 / console.c < prev    next >
C/C++ Source or Header  |  1996-05-13  |  14KB  |  608 lines

  1. #define INCL_WIN
  2. #define INCL_GPI
  3. #define INCL_DOS
  4. #define INCL_DOSERRORS
  5. #include <os2.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9.  
  10. #include "global.h"
  11. #include "system.h"
  12. #include "console.h"
  13. #include "coredefs.h"
  14.  
  15. #define CON_COLS    (MAP_COLS + 30)
  16. #define CON_ROWS    (MAP_ROWS + 20)
  17.  
  18. void EXPENTRY windowthread(ULONG arg);
  19. MRESULT EXPENTRY ElanProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
  20. void paintch(void);
  21. void makerect(RECTL *r, short r1, short c1, short r2, short c2);
  22. void makepos(POINTL *p, short r, short c);
  23. void rect2path(HPS hps, RECTL *r);
  24.  
  25. static const long colormap[] = { CLR_BLACK, CLR_BLUE, CLR_RED, CLR_PINK,
  26.        CLR_GREEN, CLR_CYAN, CLR_YELLOW, CLR_WHITE, CLR_DARKGRAY,
  27.        CLR_DARKBLUE, CLR_DARKRED, CLR_DARKPINK, CLR_DARKGREEN,
  28.        CLR_DARKCYAN, CLR_BROWN, CLR_PALEGRAY };
  29. colors_pair pen_colors[PEN_NUMBER];
  30. char        screentext[CON_ROWS * CON_COLS];
  31. int         screencolor[CON_ROWS * CON_COLS];
  32. HEV         initializationsem;
  33. int         initresult;
  34. HWND        elanhwnd;
  35. HWND        framehwnd;
  36. TID         thr;
  37. HAB         elanhab;
  38. HMQ         elanhmq;
  39. int         curr_pen = 0;
  40. signed char row;
  41. signed char col;
  42. HQUEUE        kbq;
  43. short        cursorvisible;
  44. short        cursorenabled;
  45. HPS         hps;
  46. HMTX        psaccess;
  47. short        textoffs;
  48. short       sizex;
  49. short        sizey;
  50.  
  51. int open_console(const char *title_string, int x, int y, int l, int h)
  52. {
  53.     elanhab = WinInitialize(0L);
  54.     elanhmq = WinCreateMsgQueue(elanhab, 0L);
  55.  
  56.     memset(screentext, ' ', sizeof(screentext));
  57.     memset(screencolor, 0, sizeof(screencolor));
  58.     if(DosCreateEventSem(0, &initializationsem, 0, FALSE) == 0 &&
  59.         DosCreateMutexSem(0, &psaccess, 0, FALSE) == 0 &&
  60.         DosCreateQueue(&kbq, 0, "\\QUEUES\\ELAN\\KBQUEUE") == 0 &&
  61.         DosCreateThread(&thr, windowthread, (ULONG)title_string, 0, 65536) == 0 &&
  62.         DosWaitEventSem(initializationsem, SEM_INDEFINITE_WAIT) == 0 &&
  63.         initresult == 0)
  64.     {
  65.         DosCloseEventSem(initializationsem);
  66.     }
  67.     else
  68.     {
  69.         initresult = 1;
  70.         WinDestroyMsgQueue(elanhmq);
  71.         WinTerminate(elanhab);
  72.     }
  73.  
  74.     return initresult;
  75. }
  76.  
  77. void EXPENTRY windowthread(ULONG arg)
  78. {
  79.     HAB     hab;
  80.     HMQ     hmq;
  81.     QMSG    qmsg;
  82.     ULONG    fcf = FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON |
  83.             FCF_BORDER | FCF_TASKLIST | FCF_ICON;
  84.  
  85.     initresult = 0;
  86.  
  87.     hab = WinInitialize(0L);
  88.     hmq = WinCreateMsgQueue(hab, 0L);
  89.  
  90.     WinRegisterClass(hab, "Elan", ElanProc, CS_SYNCPAINT, 0L);
  91.  
  92.     if((framehwnd = WinCreateStdWindow(HWND_DESKTOP, WS_ANIMATE,
  93.             &fcf, "Elan", (char *)arg, WS_VISIBLE, 0L, 1L, &elanhwnd)) == 0)
  94.         initresult = 1;
  95.  
  96.     DosPostEventSem(initializationsem);
  97.  
  98.     if(initresult == 0)
  99.     {
  100.         /* Event loop
  101.          */
  102.         while(WinGetMsg(hab, &qmsg, 0, 0, 0))
  103.             WinDispatchMsg(hab, &qmsg);
  104.     }
  105.  
  106.     WinDestroyWindow(framehwnd);
  107.  
  108.     WinDestroyMsgQueue(hmq);
  109.     WinTerminate(hab);
  110. }
  111.  
  112. MRESULT EXPENTRY ElanProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  113. {
  114.     static HAB        hab;
  115.     static LONG     incr[CON_COLS + 1];
  116.     MRESULT     ret = (MRESULT)FALSE;
  117.     SIZEL        size;
  118.     RECTL        rec;
  119.     RECTL        back;
  120.     HDC         hdc;
  121.     POINTL        pos;
  122.     FATTRS        font;
  123.     short        wndx;
  124.     short        wndy;
  125.     LONG        len;
  126.     LONG        run;
  127.     LONG        offs;
  128.     SIZEF        box;
  129.     FONTMETRICS fm;
  130.     short        y;
  131.     short        i;
  132.     short        tmp;
  133.     FONTMETRICS *afm = NULL;
  134.     LONG        count = 0;
  135.     short        xlimit;
  136.     short        ylimit;
  137.     short        dist;
  138.     short        mindist;
  139.     short        found;
  140.  
  141.     switch(msg)
  142.     {
  143.         case WM_CREATE :
  144.             ret = (MRESULT)TRUE;
  145.  
  146.             size.cx = 0;
  147.             size.cy = 0;
  148.  
  149.             hab = WinQueryAnchorBlock(hwnd);
  150.             hdc = WinOpenWindowDC(hwnd);
  151.             hps = GpiCreatePS(hab, hdc, &size, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
  152.  
  153.             if(hps != 0)
  154.             {
  155.                 memset(&font, 0, sizeof(font));
  156.                 font.usRecordLength = sizeof(font);
  157.  
  158.                 count = GpiQueryFonts(hps, QF_PUBLIC, "System VIO", &count,
  159.                     sizeof(*afm), (PFONTMETRICS)NULL);
  160.  
  161.                 if((afm = malloc(sizeof(*afm) * count)) != 0)
  162.                 {
  163.                     GpiQueryFonts(hps, QF_PUBLIC, "System VIO",
  164.                         &count, sizeof(*afm), afm);
  165.  
  166.                     xlimit = (0.75 * WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN)) / CON_COLS;
  167.                     ylimit = (0.75 * (WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR))) / CON_ROWS;
  168.  
  169.                     found = -1;
  170.                     for(i = 0; i < count; i++)
  171.                     {
  172.                         if(! (afm[i].fsDefn & FM_DEFN_OUTLINE) &&
  173.                             afm[i].lMaxBaselineExt <= ylimit &&
  174.                             afm[i].lAveCharWidth <= xlimit)
  175.                         {
  176.                             dist = (ylimit - afm[i].lMaxBaselineExt) + (xlimit - afm[i].lAveCharWidth);
  177.                             if(found == -1 || dist < mindist)
  178.                             {
  179.                                 mindist = dist;
  180.                                 found = i;
  181.                             }
  182.                         }
  183.                     }
  184.  
  185.                     if(found != -1)
  186.                     {
  187.                         strcpy(font.szFacename, afm[found].szFacename);
  188.                         font.idRegistry = afm[found].idRegistry;
  189.                         font.lMaxBaselineExt = afm[found].lMaxBaselineExt;
  190.                         font.lAveCharWidth = afm[found].lAveCharWidth;
  191.  
  192.                         GpiCreateLogFont(hps, 0, 42, &font);
  193.                         GpiSetCharSet(hps, 42);
  194.  
  195.                         GpiQueryFontMetrics(hps, sizeof(fm), &fm);
  196.                         sizex = fm.lMaxCharInc;
  197.                         sizey = fm.lEmHeight * 1.3 + fm.lExternalLeading;
  198.                         textoffs = fm.lMaxDescender + (sizey - fm.lEmHeight - fm.lExternalLeading) / 2;
  199.  
  200.                         for(i = 0; i < CON_COLS + 1; i++)
  201.                             incr[i] = sizex;
  202.  
  203.                         wndx = 2 * WinQuerySysValue(HWND_DESKTOP, SV_CXBORDER) +
  204.                                 CON_COLS * sizex;
  205.                         wndy = WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR) +
  206.                                 2 * WinQuerySysValue(HWND_DESKTOP, SV_CYBORDER) +
  207.                                 CON_ROWS * sizey;
  208.  
  209.                         WinSetWindowPos(WinQueryWindow(hwnd, QW_PARENT), 0, 10, 10,
  210.                             wndx, wndy, SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ACTIVATE);
  211.  
  212.                         WinStartTimer(hab, hwnd, 100, WinQuerySysValue(HWND_DESKTOP, SV_CURSORRATE));
  213.                         cursorvisible = 0;
  214.                         cursorenabled = 0;
  215.  
  216.                         ret = (MRESULT)FALSE;
  217.                     }
  218.                     free(afm);
  219.                 }
  220.             }
  221.             break;
  222.  
  223.         case WM_DESTROY :
  224.             if(DosWriteQueue(kbq, 27, 0, 0, 0) == 0 &&
  225.                 DosWriteQueue(kbq, 27, 0, 0, 0) == 0)
  226.                 GpiDestroyPS(hps);
  227.             else
  228.                 DosBeep(880, 100);
  229.             break;
  230.  
  231.         case WM_CHAR :
  232.             if(! (SHORT1FROMMP(mp1) & KC_KEYUP) && SHORT1FROMMP(mp2) != 0)
  233.                 if(DosWriteQueue(kbq, SHORT1FROMMP(mp2), 0, 0, 0) != 0)
  234.                     DosBeep(880, 100);
  235.             ret = (MRESULT)TRUE;    /* eat event */
  236.             break;
  237.  
  238.         case WM_PAINT :
  239.             DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
  240.             WinBeginPaint(hwnd, hps, &rec);
  241.             GpiSetColor(hps, CLR_BLACK);
  242.             GpiSetBackColor(hps, CLR_BLACK);
  243.             GpiSetMix(hps, FM_OVERPAINT);
  244.             GpiBeginPath(hps, 1L);
  245.             rect2path(hps, &rec);
  246.             GpiEndPath(hps);
  247.             GpiFillPath(hps, 1L, FPATH_ALTERNATE);
  248.  
  249.             for(y = 0; y < CON_ROWS; y++)
  250.             {
  251.                 pos.x = 0;
  252.                 pos.y = sizey * (CON_ROWS - 1 - y) + textoffs;
  253.  
  254.                 offs = CON_COLS * y;
  255.                 run = 0;
  256.                 do
  257.                 {
  258.                     len = 1;
  259.                     while(run + len < CON_COLS && screencolor[offs + len] == screencolor[offs])
  260.                         len++;
  261.  
  262.                     GpiSetMix(hps, FM_OVERPAINT);
  263.                     GpiSetColor(hps, colormap[pen_colors[screencolor[offs]].fg]);
  264.                     GpiSetBackColor(hps, colormap[pen_colors[screencolor[offs]].bg]);
  265.                     makerect(&back, y, run, y, run + len);
  266.                     GpiCharStringPosAt(hps, &pos, &back, CHS_VECTOR | CHS_OPAQUE,
  267.                         len, screentext + offs, incr);
  268.  
  269.                     pos.x += len * sizex;
  270.                     offs += len;
  271.                     run += len;
  272.                 }
  273.                 while(run < CON_COLS);
  274.                 pos.y -= sizey;
  275.             }
  276.             WinEndPaint(hps);
  277.             DosReleaseMutexSem(psaccess);
  278.             ret = (MRESULT)FALSE;
  279.             break;
  280.  
  281.         case WM_TIMER :
  282.             if(cursorenabled && DosRequestMutexSem(psaccess, SEM_IMMEDIATE_RETURN) == 0)
  283.             {
  284.                 makerect(&rec, row, col, row, col);
  285.                 GpiSetColor(hps, CLR_WHITE);
  286.                 GpiSetBackColor(hps, CLR_BLACK);
  287.                 GpiSetMix(hps, FM_XOR);
  288.                 GpiBeginPath(hps, 1L);
  289.                 rect2path(hps, &rec);
  290.                 GpiEndPath(hps);
  291.                 GpiFillPath(hps, 1L, FPATH_ALTERNATE);
  292.                 cursorvisible = 1 - cursorvisible;
  293.                 DosReleaseMutexSem(psaccess);
  294.             }
  295.             break;
  296.  
  297.         default :
  298.             ret = WinDefWindowProc(hwnd, msg, mp1, mp2);
  299.             break;
  300.     }
  301.  
  302.     return ret;
  303. }
  304.  
  305. void close_console()
  306. {
  307.     WinPostMsg(elanhwnd, WM_QUIT, MPVOID, MPVOID);
  308.     DosWaitThread(&thr, DCWW_WAIT);
  309.  
  310.     DosCloseMutexSem(psaccess);
  311.     DosCloseQueue(kbq);
  312.  
  313.     WinDestroyMsgQueue(elanhmq);
  314.     WinTerminate(elanhab);
  315. }
  316.  
  317. char read_char()
  318. {
  319.     REQUESTDATA req;
  320.     void        *data;
  321.     ULONG        size;
  322.     BYTE        pri;
  323.  
  324.     DosReadQueue(kbq, &req, &size, &data, 0, DCWW_WAIT, &pri, 0);
  325.  
  326.     return req.ulData;
  327. }
  328.  
  329. char async_read_char()
  330. {
  331.     REQUESTDATA req;
  332.     void        *data;
  333.     ULONG        size;
  334.     BYTE        pri;
  335.     char        c;
  336.  
  337.     if(DosReadQueue(kbq, &req, &size, &data, 0, DCWW_NOWAIT, &pri, 0) == ERROR_QUE_EMPTY)
  338.         c = 0;
  339.     else
  340.         c = req.ulData;
  341.  
  342.     return c;
  343. }
  344.  
  345. void con_printf(const char *format_string,...)
  346. {
  347.     char buffer[STRING_MAX_LEN];
  348.     va_list arg_list;
  349.  
  350.     va_start(arg_list, format_string);
  351.     vsprintf(buffer, format_string, arg_list);
  352.     write_string(buffer);
  353. }
  354.  
  355. void begin_redraw()
  356. {
  357.     hide_cursor();
  358.     clear_screen();
  359. }
  360.  
  361. void end_redraw()
  362. {
  363.     show_cursor();
  364. }
  365.  
  366. int register_pen(colors_pair pair)
  367. {
  368.     static int last_pen = 0;
  369.     int pen;
  370.  
  371.     for(pen = 0; pen < last_pen; pen++)
  372.         if(pen_colors[pen].fg == pair.fg && pen_colors[pen].bg == pair.bg)
  373.             return pen;
  374.  
  375.     pen_colors[last_pen] = pair;
  376.     pen_colors[reverse_pen(last_pen)].fg = pair.bg;
  377.     pen_colors[reverse_pen(last_pen)].bg = pair.fg;
  378.  
  379.     return last_pen++;
  380. }
  381.  
  382. void set_pen(int pen)
  383. {
  384.     curr_pen = pen;
  385. }
  386.  
  387. void locate(signed char i, signed char j)
  388. {
  389.     RECTL    rec;
  390.  
  391.     if(cursorvisible)
  392.     {
  393.         DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
  394.         makerect(&rec, row, col, row, col);
  395.         GpiSetColor(hps, CLR_WHITE);
  396.         GpiSetBackColor(hps, CLR_BLACK);
  397.         GpiSetMix(hps, FM_XOR);
  398.         GpiBeginPath(hps, 1L);
  399.         rect2path(hps, &rec);
  400.         GpiEndPath(hps);
  401.         GpiFillPath(hps, 1L, FPATH_ALTERNATE);
  402.         cursorvisible = 0;
  403.         DosReleaseMutexSem(psaccess);
  404.     }
  405.     row = i;
  406.     col = j;
  407. }
  408.  
  409. void clear_screen()
  410. {
  411.     memset(screentext, ' ', sizeof(screentext));
  412.     memset(screencolor, 0, sizeof(screencolor));
  413. }
  414.  
  415. void clear_to_eos()
  416. {
  417.     RECTL    rec;
  418.     short   pos = CON_COLS * row + col;
  419.  
  420.     memset(screentext + pos, ' ', sizeof(screentext) - pos * sizeof(screentext[0]));
  421.     memset(screencolor + pos, 0, sizeof(screencolor) - pos * sizeof(screencolor[0]));
  422.  
  423.     DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
  424.  
  425.     makerect(&rec, row, col, row, CON_COLS - 1);
  426.     GpiSetColor(hps, CLR_BLACK);
  427.     GpiSetBackColor(hps, CLR_BLACK);
  428.     GpiSetMix(hps, FM_OVERPAINT);
  429.     GpiBeginPath(hps, 1L);
  430.     rect2path(hps, &rec);
  431.     GpiEndPath(hps);
  432.     GpiFillPath(hps, 1L, FPATH_ALTERNATE);
  433.  
  434.     makerect(&rec, row + 1, 0, CON_ROWS - 1, CON_COLS - 1);
  435.     GpiSetColor(hps, CLR_BLACK);
  436.     GpiSetBackColor(hps, CLR_BLACK);
  437.     GpiSetMix(hps, FM_OVERPAINT);
  438.     GpiBeginPath(hps, 1L);
  439.     rect2path(hps, &rec);
  440.     GpiEndPath(hps);
  441.     GpiFillPath(hps, 1L, FPATH_ALTERNATE);
  442.  
  443.     DosReleaseMutexSem(psaccess);
  444. }
  445.  
  446. void clear_to_eol()
  447. {
  448.     RECTL    rec;
  449.     short    pos = CON_COLS * row + col;
  450.     short    size = CON_COLS - col;
  451.  
  452.     memset(screentext + pos, ' ', size * sizeof(screentext[0]));
  453.     memset(screencolor + pos, 0, size * sizeof(screencolor[0]));
  454.  
  455.     DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
  456.  
  457.     makerect(&rec, row, col, row, CON_COLS - 1);
  458.     GpiSetColor(hps, CLR_BLACK);
  459.     GpiSetBackColor(hps, CLR_BLACK);
  460.     GpiSetMix(hps, FM_OVERPAINT);
  461.     GpiBeginPath(hps, 1L);
  462.     rect2path(hps, &rec);
  463.     GpiEndPath(hps);
  464.     GpiFillPath(hps, 1L, FPATH_ALTERNATE);
  465.  
  466.     DosReleaseMutexSem(psaccess);
  467. }
  468.  
  469. void show_cursor()
  470. {
  471.     cursorenabled = 1;
  472. }
  473.  
  474. void hide_cursor()
  475. {
  476.     RECTL    rec;
  477.  
  478.     cursorenabled = 0;
  479.     if(cursorvisible)
  480.     {
  481.         DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
  482.         makerect(&rec, row, col, row, col);
  483.         GpiSetColor(hps, CLR_WHITE);
  484.         GpiSetBackColor(hps, CLR_BLACK);
  485.         GpiSetMix(hps, FM_XOR);
  486.         GpiBeginPath(hps, 1L);
  487.         rect2path(hps, &rec);
  488.         GpiEndPath(hps);
  489.         GpiFillPath(hps, 1L, FPATH_ALTERNATE);
  490.         cursorvisible = 0;
  491.         DosReleaseMutexSem(psaccess);
  492.     }
  493. }
  494.  
  495. void write_char(char output_char)
  496. {
  497.     if(output_char == 0x0a)
  498.     {
  499.         col = 0;
  500.         row++;
  501.         if(row == CON_ROWS)
  502.             row = 0;
  503.     }
  504.     else
  505.     {
  506.         screentext[CON_COLS * row + col] = output_char;
  507.         screencolor[CON_COLS * row + col] = curr_pen;
  508.         paintch();
  509.         col++;
  510.         if(col == CON_COLS)
  511.         {
  512.             col = 0;
  513.             row++;
  514.             if(row == CON_ROWS)
  515.                 row = 0;
  516.         }
  517.     }
  518. }
  519.  
  520. void write_string(const char *string)
  521. {
  522.     while(*string)
  523.     {
  524.         if(*string == 0x0a)
  525.         {
  526.             col = 0;
  527.             row++;
  528.             if(row == CON_ROWS)
  529.                 row = 0;
  530.         }
  531.         else
  532.         {
  533.             screentext[CON_COLS * row + col] = *string;
  534.             screencolor[CON_COLS * row + col] = curr_pen;
  535.             paintch();
  536.             col++;
  537.             if(col == CON_COLS)
  538.             {
  539.                 col = 0;
  540.                 row++;
  541.                 if(row == CON_ROWS)
  542.                     row = 0;
  543.             }
  544.         }
  545.         string++;
  546.     }
  547. }
  548.  
  549. void paintch(void)
  550. {
  551.     short    offs = CON_COLS * row + col;
  552.     POINTL  pos;
  553.     RECTL    back;
  554.  
  555.     DosRequestMutexSem(psaccess, SEM_INDEFINITE_WAIT);
  556.  
  557.     GpiSetMix(hps, FM_OVERPAINT);
  558.     GpiSetColor(hps, colormap[pen_colors[screencolor[offs]].fg]);
  559.     GpiSetBackColor(hps, colormap[pen_colors[screencolor[offs]].bg]);
  560.     makepos(&pos, row, col);
  561.     makerect(&back, row, col, row, col);
  562.     GpiCharStringPosAt(hps, &pos, &back, CHS_OPAQUE, 1, screentext + offs, 0);
  563.  
  564.     DosReleaseMutexSem(psaccess);
  565. }
  566.  
  567. void makerect(RECTL *r, short r1, short c1, short r2, short c2)
  568. {
  569.     short    t;
  570.     if(r2 < r1)
  571.         t = r1, r1 = r2, r2 = t;
  572.     if(c2 < c1)
  573.         t = c1, c1 = c2, c2 = t;
  574.  
  575.     r->xLeft = sizex * c1;
  576.     r->xRight = sizex * c2 + sizex - 1;
  577.     r->yTop = sizey * (CON_ROWS - 1 - r1) + sizey - 1;
  578.     r->yBottom = sizey * (CON_ROWS - 1 - r2);
  579. }
  580.  
  581. void makepos(POINTL *p, short r, short c)
  582. {
  583.     p->x = sizex * c;
  584.     p->y = sizey * (CON_ROWS - 1 - r) + textoffs;
  585. }
  586.  
  587. void rect2path(HPS hps, RECTL *r)
  588. {
  589.     POINTL    pos;
  590.  
  591.     pos.x = r->xLeft;
  592.     pos.y = r->yBottom;
  593.     GpiMove(hps, &pos);
  594.     pos.x = r->xRight;
  595.     pos.y = r->yBottom;
  596.     GpiLine(hps, &pos);
  597.     pos.x = r->xRight;
  598.     pos.y = r->yTop;
  599.     GpiLine(hps, &pos);
  600.     pos.x = r->xLeft;
  601.     pos.y = r->yTop;
  602.     GpiLine(hps, &pos);
  603.     pos.x = r->xLeft;
  604.     pos.y = r->yBottom;
  605.     GpiLine(hps, &pos);
  606. }
  607.  
  608.